package com.hiwi.provider.notify.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;

import com.alibaba.fastjson.JSONObject;

/**
 * xml工具类
 * 
 * @author <a href="mailto:luozj@hiwitech.com">luozhongjie</a>
 * @version 1.0
 */
public class XmlUtils {

    /**
     * 解析xml文件,并转换成Json
     * 
     * @param xml
     * @return
     */
    public static JSONObject xmlToJson(String xml) {
        JSONObject obj = new JSONObject();
        try {
            // 将String转换成xml文件
            Document document = DocumentHelper.parseText(xml);
            // 获取根节点
            Element rootElement = document.getRootElement();
            obj.put(rootElement.getName(), iterateElement(rootElement));
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * XML转MAP
     * 
     * @param xmlString
     * @return
     * @throws DocumentException
     */
    public static Map<String, Object> xml2map(String xmlString) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Document doc = DocumentHelper.parseText(xmlString);
            Element rootElement = doc.getRootElement();
            ele2map(map, rootElement);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return map;
    }

    /***
     * 核心方法，里面有递归调用
     * 
     * @param map
     * @param ele
     */
    @SuppressWarnings("unchecked")
    static void ele2map(Map<String, Object> map, Element ele) {
        // 获得当前节点的子节点
        List<Element> elements = ele.elements();
        if (elements.size() == 0) {
            // 没有子节点说明当前节点是叶子节点，直接取值即可
            map.put(ele.getName(), ele.getText());
        } else if (elements.size() == 1) {
            // 只有一个子节点说明不用考虑list的情况，直接继续递归即可
            Map<String, Object> tempMap = new HashMap<String, Object>();
            ele2map(tempMap, elements.get(0));
            map.put(ele.getName(), tempMap);
        } else {
            // 多个子节点的话就得考虑list的情况了，比如多个子节点有节点名称相同的
            // 构造一个map用来去重
            Map<String, Object> tempMap = new HashMap<String, Object>();
            for (Element element : elements) {
                tempMap.put(element.getName(), null);
            }
            Set<String> keySet = tempMap.keySet();
            for (String string : keySet) {
                Namespace namespace = elements.get(0).getNamespace();
                List<Element> elements2 = ele.elements(new QName(string, namespace));
                // 如果同名的数目大于1则表示要构建list
                if (elements2.size() > 1) {
                    List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
                    for (Element element : elements2) {
                        Map<String, Object> tempMap1 = new HashMap<String, Object>();
                        ele2map(tempMap1, element);
                        list.add(tempMap1);
                    }
                    map.put(string, list);
                } else {
                    // 同名的数量不大于1则直接递归去
                    ele2map(map, elements2.get(0));
                }
            }
        }
    }

    /**
     * 遍历xml数据结构
     * 
     * @param element
     * @return
     */
    @SuppressWarnings({ "rawtypes" })
    private static JSONObject iterateElement(Element element) {
        List elements = element.elements();
        if (null == elements || elements.size() == 0) {
            return new JSONObject();
        }
        Element et = null;
        JSONObject elementJson = new JSONObject();
        for (int i = 0; i < elements.size(); i++) {
            et = (Element) elements.get(i);
            if (elementJson.containsKey(et.getName())) {
                continue;
            }
            elementJson.put(et.getName(), et.getTextTrim());
        }
        return elementJson;
    }

    /**
     * 多级xml转换成json
     * 
     * @param xmlString
     * @return
     */
    public static JSONObject xml2Json(String xmlString) {
        JSONObject jsonObj = new JSONObject();
        try {
            Document doc = DocumentHelper.parseText(xmlString);
            Element rootElement = doc.getRootElement();
            ele2Json(jsonObj, rootElement);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return jsonObj;
    }

    @SuppressWarnings("unchecked")
    static void ele2Json(JSONObject jsonObj, Element ele) {
        // 获得当前节点的子节点
        List<Element> elements = ele.elements();
        if (elements.size() == 0) {
            // 没有子节点说明当前节点是叶子节点，直接取值即可
            jsonObj.put(ele.getName(), ele.getText());
        } else if (elements.size() == 1) {
            // 只有一个子节点说明不用考虑list的情况，直接继续递归即可
            Map<String, Object> tempMap = new HashMap<String, Object>();
            ele2map(tempMap, elements.get(0));
            jsonObj.put(ele.getName(), tempMap);
        } else {
            // 多个子节点的话就得考虑list的情况了，比如多个子节点有节点名称相同的
            // 构造一个map用来去重
            JSONObject tempJson = new JSONObject();
            for (Element element : elements) {
                tempJson.put(element.getName(), null);
            }
            Set<String> keySet = tempJson.keySet();
            for (String string : keySet) {
                Namespace namespace = elements.get(0).getNamespace();
                List<Element> elements2 = ele.elements(new QName(string, namespace));
                // 如果同名的数目大于1则表示要构建list
                if (elements2.size() > 1) {
                    List<JSONObject> list = new ArrayList<JSONObject>();
                    for (Element element : elements2) {
                        JSONObject tempJson1 = new JSONObject();
                        ele2map(tempJson1, element);
                        list.add(tempJson1);
                    }
                    jsonObj.put(string, list);
                } else {
                    // 同名的数量不大于1则直接递归去
                    ele2map(jsonObj, elements2.get(0));
                }
            }
        }
    }

    /**
     * Map转Xml
     * 
     * @param map
     *            Map对象
     * @param rootName
     *            根节点名称
     * @param isHead
     *            是否需要头标签
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String mapToXML(Map map, String rootName, boolean isHead) {
        StringBuffer sb = new StringBuffer();
        if (isHead) {
            sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        }
        sb.append("<" + rootName + ">");
        packagingXml(map, sb);
        sb.append("</" + rootName + ">");
        return sb.toString();
    }

    /**
     * 封装Xml
     * 
     * @param map
     * @param sb
     */
    @SuppressWarnings("rawtypes")
    private static void packagingXml(Map map, StringBuffer sb) {
        Set set = map.keySet();
        for (Iterator it = set.iterator(); it.hasNext();) {
            String key = (String) it.next();
            Object value = map.get(key);
            if (null == value)
                value = "";
            if (value.getClass().getName().equals("java.util.ArrayList")) {
                ArrayList list = (ArrayList) map.get(key);
                sb.append("<" + key + ">");
                for (int i = 0; i < list.size(); i++) {
                    HashMap hm = (HashMap) list.get(i);
                    packagingXml(hm, sb);
                }
                sb.append("</" + key + ">");

            } else {
                if (value instanceof HashMap) {
                    sb.append("<" + key + ">");
                    packagingXml((HashMap) value, sb);
                    sb.append("</" + key + ">");
                } else {
                    sb.append("<" + key + ">" + value + "</" + key + ">");
                }

            }

        }
    }

    public static void main(String[] args) {
        // String xml = "<?xml version=\"1.0\" encoding=\"GB2312\" ?>";
        // xml += "<orderinfo> ";
        // xml += "<err_msg></err_msg>";
        // xml += "<retcode>1</retcode>";
        // xml += "<orderid>S1404150533235</orderid> ";
        // xml += "<cardid>6444600</cardid> ";
        // xml += "<cardnum>2</cardnum> ";
        // xml += " <ordercash>222</ordercash>  ";
        // xml += "<cardname>全国中石化加油充值卡 100元直充</cardname> ";
        // xml += "<sporder_id>sinopecorder</sporder_id> ";
        // xml += "<game_userid>123456</game_userid>";
        // xml += "<game_state>0</game_state>";
        // xml += "</orderinfo>";
        // XmlUtils xmlUtils = new XmlUtils();
        // JSONObject jsonStr = xmlUtils.xmlToJson(xml);
        // System.out.println(jsonStr.toString());
    }
}
